/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "log/Log.h"
#include "gmock/gmock-actions.h"
#include "ArchiveDownloadFile.h"
#include "io_device/FileDef.h"
#include "ArchiveClient.h"
#include "application/ApplicationManager.h"
#include "PluginUtilities.h"
#include "ScannerUtils.h"

#include "gtest/gtest.h"
#include "mockcpp/mockcpp.hpp"

using namespace std;

namespace {
    constexpr auto FILE_FULL_PATH = "/tmp/ArchiveDownloadFileTest.txt";
}

class ArchiveDownloadFileTest2 : public testing::Test {
public:
    void SetUp();
    void TearDown();
    static void SetUpTestCase();
    static void TearDownTestCase();
    std::unique_ptr<ArchiveDownloadFile> m_ins = nullptr;
    std::unique_ptr<ArchiveStreamService> m_clientHandler = std::make_unique<ArchiveStreamService>();
};

void ArchiveDownloadFileTest2::SetUp()
{
    ArchiveServerInfo info{};
    info.ipList.push_back("aaa");
    info.ipList.push_back("bbb");
    std::string jobId = "job123";
    std::string copyId = "copy123";
    bool isDownloadMeta = true;
    m_ins = std::make_unique<ArchiveDownloadFile>(jobId, copyId, info, isDownloadMeta);
}

void ArchiveDownloadFileTest2::TearDown()
{
    GlobalMockObject::verify(); // 校验mock规范并清除mock规范
}

void ArchiveDownloadFileTest2::SetUpTestCase()
{}

void ArchiveDownloadFileTest2::TearDownTestCase()
{}

/*
 * 用例名称: StartDownloadMeta
 * 前置条件：无
 * check点：开始下载meta
 */
static bool StubGetControlFileFromArchiveFalse(ArchiveDownloadFile* This, std::string& checkpoint, std::vector<std::string>& controlList)
{
    controlList.push_back("aaa");
    return false;
}
static bool StubGetControlFileFromArchiveTrue(ArchiveDownloadFile* This, std::string& checkpoint, std::vector<std::string>& controlList)
{
    controlList.push_back("aaa");
    return true;
}
TEST_F(ArchiveDownloadFileTest2, StartDownloadMeta)
{
    MOCKER_CPP(&ArchiveDownloadFile::InitArchiveClient)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&ArchiveDownloadFile::GetControlFileFromArchive)
            .stubs()
            .will(invoke(StubGetControlFileFromArchiveFalse))
            .then(invoke(StubGetControlFileFromArchiveTrue));
    MOCKER_CPP(&ArchiveDownloadFile::GetFileListFromCtrl)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    MOCKER_CPP(&ArchiveDownloadFile::DownloadFile)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    std::string outputPath;
    std::vector<std::string> pathList;
    m_ins->m_isInit = false;    
    EXPECT_EQ(m_ins->StartDownloadMeta(outputPath, pathList), false);
    EXPECT_EQ(m_ins->StartDownloadMeta(outputPath, pathList), false);
    EXPECT_EQ(m_ins->StartDownloadMeta(outputPath, pathList), false);
    m_ins->m_isDownloadMeta = false;
    EXPECT_EQ(m_ins->StartDownloadMeta(outputPath, pathList), true);
    m_ins->m_isDownloadMeta = true;
    EXPECT_EQ(m_ins->StartDownloadMeta(outputPath, pathList), true);
}

/*
 * 用例名称: QueryPrepare
 * 前置条件：无
 * check点：获取控制文件
 */
static int StubQueryPrepareStatus(ArchiveStreamService* This, int& state) 
{
    state = 2;
    return 0;
}
static int StubQueryPrepareStatus2(ArchiveStreamService* This, int& state) 
{
    state = -1;
    return 0;
}
static int StubQueryPrepareStatus3(ArchiveStreamService* This, int& state) 
{
    state = 3;
    return 0;
}
TEST_F(ArchiveDownloadFileTest2, QueryPrepare)
{ 
    MOCKER_CPP(&ArchiveStreamService::PrepareRecovery)
            .stubs()
            .will(returnValue(0));
    MOCKER_CPP(&ArchiveStreamService::QueryPrepareStatus)
            .stubs()
            .will(invoke(StubQueryPrepareStatus))
            .then(invoke(StubQueryPrepareStatus2))
            .then(invoke(StubQueryPrepareStatus3));
    MOCKER((std::this_thread::sleep_for<int64_t, std::ratio<1>>)) 
            .stubs() 
            .will(ignoreReturnValue());
    EXPECT_EQ(m_ins->QueryPrepare(), false);
    EXPECT_EQ(m_ins->QueryPrepare(), true);
    EXPECT_EQ(m_ins->QueryPrepare(), true);
}

/*
 * 用例名称: GetControlFileFromArchive
 * 前置条件：无
 * check点：获取控制文件
 */
// TEST_F(ArchiveDownloadFileTest2, GetFileListFromCtrl)
// {
//     std::ofstream file(FILE_FULL_PATH);
//     file << "111,222,333,444,555,666,777" << endl;
//     file.close();
//     std::string ctrlFileName = FILE_FULL_PATH;
//     std::map<std::string, ControlFileData> ctrlFileMap;
//     EXPECT_EQ(m_ins->GetFileListFromCtrl("/file.txt", ctrlFileMap), false);
//     EXPECT_EQ(m_ins->GetFileListFromCtrl(ctrlFileName, ctrlFileMap), true);
// }

/*
 * 用例名称: OpenFileExistOrNew
 * 前置条件：无
 * check点：获取控制文件
 */
TEST_F(ArchiveDownloadFileTest2, OpenFileExistOrNew)
{
    m_ins->m_fileFullPath = "";
    EXPECT_EQ(m_ins->OpenFileExistOrNew(), -1);
    m_ins->m_fileFullPath = FILE_FULL_PATH;
    EXPECT_EQ(m_ins->OpenFileExistOrNew(), 0);    
}

static int StubGetFileData_1(ArchiveStreamService* This, ArchiveStreamGetFileReq& req, ArchiveStreamGetFileRsq& rsq) {
    rsq.readEnd = 1;
    return 1;
}
static int StubGetFileData_0(ArchiveStreamService* This, ArchiveStreamGetFileReq& req, ArchiveStreamGetFileRsq& rsq) {
    rsq.readEnd = 1;
    return 0;
}

/*
 * 用例名称: WriteFile
 * 前置条件：无
 * check点：下载文件
 */
TEST_F(ArchiveDownloadFileTest2, WriteFile)
{
    // MOCKER_CPP(&ArchiveStreamService::GetFileData)
    //         .stubs()
    //         .will(invoke(StubGetFileData_1))
    //         .then(invoke(StubGetFileData_0));
    // MOCKER_CPP(&ArchiveDownloadFile::WriteBufferToFile)
    //         .stubs()
    //         .will(returnValue(1))
    //         .then(returnValue(0));
    // ControlFileData ctrlData;
    // EXPECT_EQ(m_ins->WriteFile(ctrlData), false);
    // EXPECT_EQ(m_ins->WriteFile(ctrlData), true);
    // EXPECT_EQ(m_ins->WriteFile(ctrlData), true);
}

/*
 * 用例名称: DownloadFile
 * 前置条件：无
 * check点：下载文件
 */
TEST_F(ArchiveDownloadFileTest2, DownloadFile)
{
    MOCKER_CPP(&PluginUtils::RecurseCreateDirectory)
            .stubs()
            .will(returnValue(false)); 
    MOCKER_CPP(&ArchiveDownloadFile::OpenFileExistOrNew)
            .stubs()
            .will(returnValue(-1))
            .then(returnValue(0));
    MOCKER_CPP(&ArchiveDownloadFile::WriteFile)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));
    std::map<std::string, ControlFileData> ctrlFileMap;
    ControlFileData controlFileData;
    ctrlFileMap[""] = controlFileData;   
    EXPECT_EQ(m_ins->DownloadFile("", ctrlFileMap), false);
    EXPECT_EQ(m_ins->DownloadFile("", ctrlFileMap), false);
    EXPECT_EQ(m_ins->DownloadFile("", ctrlFileMap), true);
    std::map<std::string, ControlFileData> ctrlFileMap2;
    ControlFileData controlFileData2;
    ctrlFileMap2["/"] = controlFileData2;  
    EXPECT_EQ(m_ins->DownloadFile("/tmp", ctrlFileMap2), false);
}


